/**		
 *
 *  Copyright (c) 2009 Lean Mean Fighting Machine Ltd.
 *	
 *  @version 1.00 | Sep 30, 2009
 *  @author Justin Windle
 *  
 **/
 
package uk.co.lmfm.util
{
	import flash.xml.XMLDocument;
	import flash.xml.XMLNode;
	import flash.xml.XMLNodeType;

	/**
	 *  StringUtil
	 */
	public class StringUtil 
	{
		public static const STRIP_TAGS : RegExp = /<[^>]+>/g;
		public static const FILE_LOCATION : RegExp = /.+(\/)(?=.+\.)/;
		public static const FILE_EXTENSION : RegExp = /\.([^\.]+)$/;
		public static const CLEAN_WHITESPACE : RegExp = /\s+/g;
		public static const TRIM_WHITESPACE : RegExp = /^\s+|\s+$/g;
		public static const EXTRACT_DOMAIN : RegExp = /^([a-zA-Z]+:\/\/)?([^\/]+)\/.*?$/;
		public static const VALIDATE_EMAIL : RegExp = /^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(([0-9]{1,3})|([a-zA-Z]{2,3})|(aero|coop|info|museum|name))$/;
		//public static const VALIDATE_URL : RegExp = /^(http\:\/\/[a-zA-Z0-9_\-]+(?:\.[a-zA-Z0-9_\-]+)*\.[a-zA-Z]{2,4}(?:\/[a-zA-Z0-9_\-]+)*(?:\/[a-zA-Z0-9_]+\.[a-zA-Z]{2,4}(?:\?[a-zA-Z0-9_\-]+=[a-zA-Z0-9_\-]+)?)?(?:\&[a-zA-Z0-9_\-]+\=[a-zA-Z0-9_\-]+)*)$/;
		public static const VALIDATE_URL : RegExp = /^(http?(s)?\:\/\/[a-zA-Z0-9_\-]+(?:\.[a-zA-Z0-9_\-]+)*\.[a-zA-Z]{2,4}(?:\/[a-zA-Z0-9_\-]+)*(?:\/[a-zA-Z0-9_]+\.[a-zA-Z]{2,4}(?:\?[a-zA-Z0-9_\-]+=[a-zA-Z0-9_\-]+)?)?(?:\&[a-zA-Z0-9_\-]+\=[a-zA-Z0-9_\-]+)*)?\/?$/;
		public static const VALIDATE_IP : RegExp = /^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$/;

		//	----------------------------------------------------------------
		//	PUBLIC STATIC METHODS
		//	----------------------------------------------------------------
		
		/**
		 * Removes whitespace from the start and end of a String
		 * 
		 * @author Justin Windle
		 * @param text The String to trim
		 * @return The modified String
		 */

		public static function trim(text : String) : String
		{
			return text.replace(TRIM_WHITESPACE, "");
		}

		/**
		 * Removes extra spaces from a String and replaces them with a single space
		 * 
		 * @author Justin Windle
		 * @param text The String to clean
		 * @return The modified String
		 */

		public static function clean(text : String) : String
		{
			return trim(text.replace(CLEAN_WHITESPACE, " ").replace(/\s+\./, "."));
		}

		/**
		 * Truncates a String after a specified amount and optionally 
		 * appends characters to the end
		 * 
		 * @author Justin Windle
		 * @param text The text to truncate
		 * @param limit The position to truncate the String at
		 * @param append An optional String to append to the truncated String
		 */

		public static function truncate(text : String, limit : int, append : String = "...") : String
		{
			return text.length > limit ? text.substr(0, limit) + append : text;
		}

		/**
		 * Strips the specified tag from a String
		 * 
		 * @author Justin Windle
		 * @param text The String to strip tags from
		 * @param tag The tag to remove, minus brackets, e.g. div
		 * @return The Modified String
		 */

		public static function stripTag(text : String, tag : String) : String
		{
			return text.replace(new RegExp("<[/" + tag + "]+>", "g"), "");
		}

		/**
		 * Strips all tags from a String
		 * 
		 * @author Justin Windle
		 * @param text The String to strip tags from
		 * @return The Modified String
		 */

		public static function stripTags(text : String) : String
		{
			return text.replace(STRIP_TAGS, "");
		}

		/**
		 * Strips extra slashes from a URL while omitting the double
		 * slash after http:
		 * 
		 * For example http://www.domain.com///data//config.xml
		 * is trimmed to become http://www.domain.com/data/config.xml
		 * 
		 * This can be useful for cleaning URLs which have been
		 * constructed dynamically when certain paths are blank
		 * 
		 * @author Justin Windle
		 * @param url The URL to strip extra slashes from
		 * @return The cleaned URL
		 */

		public static function stripSlashes(url : String) : String
		{
			return url.replace(new RegExp("(?<!:)/+", "ig"), "/");
		}
		
		/**
		 * Converts a class name including the package to the filepath for the class.
		 * For example: uk.co.lmfm.Application.as becomes uk/co/lmfm/Application.as
		 * 
		 * @author Justin Windle
		 * @param text A qualified classpath, e.g. uk.co.lmfm.Application.as
		 * @return The filepath of the class, e.g. uk/co/lmfm/Application.as
		 */

		public static function classToFilepath(text : String) : String
		{
			return text.replace(/\.(\b\w{2,})(?!$)/g, '/$1');
		}

		/**
		 * Extracts all content within a specified tag from a String. Useful 
		 * for extracting the text from all anchor tags in HTML for example
		 * 
		 * @author Justin Windle
		 * @param text The String to analyse
		 * @param tag The tag to search for, minus brackets, e.g. div
		 * @return An Array of values found within the tags
		 */

		public static function extractTags(text : String, tag : String) : Array
		{
			var logic : String = "<" + tag + "[^>]*?>.*?</" + tag + ">";
			var matches : Array = text.match(new RegExp(logic, "g"));
			
			for (var i : int = 0;i < matches.length;i++)
			{
				matches[i] = matches[i].replace(/<[^>]+>/g, "");
			}
			
			return matches;
		}

		/**
		 * Extracts the domain form a url and returns the domain
		 * 
		 * @author Justin Windle
		 * @param url The URL in whuch to find the domain
		 * @return The domain of the url
		 */

		public static function extractDomain(url : String) : String
		{
			return url.replace(EXTRACT_DOMAIN, "$2").replace("www.", "");
		}

		/**
		 * Returns the file extension from a path or file name
		 * 
		 * @author Justin Windle
		 * @param path The path or file name
		 * @param removeDot Whether or not to remove the dot
		 * @return The file type of a path or file name
		 */

		public static function fileType(path : String, removeDot : Boolean = true) : String
		{
			return path.match(FILE_EXTENSION)[removeDot ? 1 : 0].replace(/\?.*/, "");
		}

		/**
		 * Returns the location of a file (the full path excluding the file)
		 * For example, passing http://site.com/swf/mov.swf?t=1234 will return http://site.com/swf/
		 */

		public static function fileLocation(path : String) : String
		{
			var result : Array = path.match(FILE_LOCATION);
			return result ? result[0] : path;
		}

		/**
		 * Checks whether an email address is in the format user[at]domain.ext
		 * 
		 * @author Justin Windle
		 * @param email The email address to validate
		 * @return Whether or not the email address is in a valid format
		 */

		public static function validateEmail(email : String) : Boolean
		{
			return email.match(VALIDATE_EMAIL) ? true : false;
		}

		/**
		 * Checks whether a URL is valid.
		 * Will only accept hyper text transfer protocol (http)
		 * Accepts multiple subdomains, subdirectories and query strings.
		 * 
		 * Examples:
		 * 
		 * http://subdomain.web-site.com/cgi-bin/perl.cgi?key1=value1&key2=value2 (OK)
		 * http://website.com/perl.cgi?key= (Not OK)
		 * 
		 * @author Justin Windle
		 * @param url The URL you wish to validate
		 * @return Whether or not the URL is valid
		 */

		public static function validateURL(url : String) : Boolean
		{
			return url.match(VALIDATE_URL) ? true : false;
		}

		/**
		 * Checks whether an IP adress is valid or not
		 * 
		 * @author Justin Windle
		 * @param ip The IP address to validate
		 * @return Whether or not the IP address is in a valid format
		 */

		public static function validateIP(ip : String) : Boolean
		{
			return ip.match(VALIDATE_IP) ? true : false;
		}

		/**
		 * Formats a number to a string and prepends zeros if necessary. 
		 * For example passing 54 as value and 3 as zeros will return 054
		 * 
		 * @author Justin Windle
		 * @param value The initial value to format
		 * @param zeros The maximum amount of zeros to add, e.g. for numbers up to 100 use 3
		 * @return String A string representation of a number with preceeding zeros
		 */

		public static function addZeros(value : Number, zeros : int) : String
		{
			for (var s : String = String((value + 0.5) << 0).replace(/\-/g, "");s.length < zeros;s = "0" + s)
			{
			}
			return value < 0 ? "-" + s : s;
		}

		/**
		 * Converts special symbols in a string to HTML entities. For example, & becomes &amp;
		 * 
		 * @author Justin Windle
		 * @param text The text to convert to HTML entities
		 * @return The text with HTML entities
		 */

		public static function htmlEscape(text : String) : String
		{
			return XML(new XMLNode(XMLNodeType.TEXT_NODE, text)).toXMLString();
		}

		/**
		 * Replaces HTML entities in a string with their corrosponding symbols, for example &amp; becomes &
		 * 
		 * @author Justin Windle
		 * @param text The text which should have HTML entities replaced by symbols
		 * @return The text after having HTML entities replaced by symbols
		 */

		public static function htmlUnescape(text : String) : String
		{
			return new XMLDocument(text).firstChild.nodeValue;
		}
	}
}
